package cn.johnyu.server;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;
import java.util.concurrent.Executors;

public class LoginServer implements Runnable{
    private static final String tip="请输入用户名和密码（用 ：分隔,如输入 ls 查看登录用户信息）\n";
    //内存模拟的用户数据库
    private static Map<String,String> userDb;
    static {
        userDb=new HashMap<>();
        userDb.put("john","123");
        userDb.put("tom","234");
        userDb.put("alice","345");
    }

    // 内存模拟的登录用户的tokens 池（生产环境使用Redis）
    private static Map<String,String> tokens=new Hashtable<>();

    private boolean running=true;

    private ServerSocket serverSocket;
    private Socket socket;

    private BufferedReader reader;
    private OutputStream outputStream;

    //服务启动（在一个子线程中）
    public void start(int port) throws Exception{
        serverSocket=new ServerSocket(port);
        socket = serverSocket.accept();
        reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        outputStream = socket.getOutputStream();

        Executors.newSingleThreadExecutor()
                .submit(this);
    }

    @Override
    public void run() {
        //力求简化，登录服务使用一个子线程完成，即在登录交互过程中，不能有第二个用户访问
        while (running) {
            try {
                outputStream.write(tip.getBytes());//首先显示给客户端提示信息
                String info = reader.readLine();//等待用户的输入
                //如果输入"ls" 展示出所有用户的登录信息
                if(info.startsWith("ls")){
                    StringBuilder builder=new StringBuilder();
                    tokens.forEach((token,name)->{
                        builder.append(name+"\t"+token+"\n");
                    });
                    outputStream.write(builder.toString().getBytes());
                }
                //如果使用"用户名：密码" 的形式，则判断：
                //1. 成功：将token放入tokens中，并返回给用户token
                //2. 失败：返回错误
                else{
                    String[] auth = info.split(":");
                    if (userDb.get(auth[0]).equals(auth[1])) {
                        String token = UUID.randomUUID().toString();
                        tokens.put(token,auth[0]);
                        outputStream.write((token + "\n").getBytes());
                    } else {
                        outputStream.write("用户名密码错误\n".getBytes());
                    }
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
//    检查token是否存在，成功返回用户名，失败返回null ,此功能由ChatRoom的active方法调用
    public static String check(String token){
        return tokens.get(token);
    }
}
